﻿using Mozhi.Abp.Domain.BasicData;
using mozhi.smarterp.Business.Products.Repositories;
using mozhi.smarterp.Business.Products.Services;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
using Mozhi.Abp.Domain.BasicData.Repositories;
using mozhi.smarterp.Business.Enums;
using Volo.Abp.ObjectMapping;

namespace mozhi.smarterp.Business.Products
{
    public class ProductInventorySettingAppService : BusinessAppService, IProductInventorySettingAppService
    {
        private IProductInventorySettingRepository _repository;
        private ProductInventorySettingManager _manager;
        private IProductRepository _productRepository;
        private IWarehouseRepository _warehouseRepository;

        public ProductInventorySettingAppService(IProductInventorySettingRepository repository, ProductInventorySettingManager manager, IProductRepository productRepository,
            IWarehouseRepository warehouseRepository)
        {
            _repository = repository;
            _manager = manager;
            _productRepository = productRepository;
            _warehouseRepository = warehouseRepository;
        }

        public async Task<ProductInventorySettingDto> CreateAsync(ProductInventorySettingCreateDto input)
        {
            var inventorySetting = await _manager.GetAsync(null, input.ProductId, input.DefaultWarehouseId, input.DefaultLocationId,  input.PricingType, input.EnableBatchNumber,
             input.EnableShelfLife, input.ShelfLifeDays, input.EnableSerialNumber, input.MinStockQuantity, input.MaxStockQuantity, input.SafetyStockQuantity, input.ReorderPointQuantity);

            inventorySetting = await _repository.InsertAsync(inventorySetting);

            var result = ObjectMapper.Map<ProductInventorySetting, ProductInventorySettingDto>(inventorySetting);

            await LoadOtherInfoAsync(new List<ProductInventorySettingDto> { result });

            return result;
        }

        public async Task DeleteAsync(Guid productId)
        {
            var setting = await _repository.GetByProductIdAsync(productId);
            if (setting == null)
                return;

            await _repository.DeleteAsync(setting.Id);
        }

        public async Task<ProductInventorySettingDto> GetAsync(Guid productId)
        {
            var inventorySetting = await _repository.GetByProductIdAsync(productId);

            var result = ObjectMapper.Map<ProductInventorySetting, ProductInventorySettingDto>(inventorySetting);

            if (result == null)
                return result;

            await LoadOtherInfoAsync(new List<ProductInventorySettingDto> { result });

            return result;
        }

        public async Task<PagedResultDto<ProductInventorySettingDto>> GetListAsync(PagedAndSortedResultRequestDto filter)
        {
            var inventorySettings = await _repository.GetPagedListAsync(filter.SkipCount, filter.MaxResultCount, filter.Sorting);

            var count = await _repository.GetCountAsync();

            var items = ObjectMapper.Map<List<ProductInventorySetting>, List<ProductInventorySettingDto>>(inventorySettings);

            await LoadOtherInfoAsync(items);

            return new PagedResultDto<ProductInventorySettingDto>()
            {
                Items = items,
                TotalCount = count
            };
        }

        public async Task<ProductInventorySettingDto> UpdateAsync(ProductInventorySettingUpdateDto input)
        {
            var inventorySetting = await _manager.GetAsync(input.Id, input.ProductId, input.DefaultWarehouseId, input.DefaultLocationId, input.PricingType, input.EnableBatchNumber,
             input.EnableShelfLife, input.ShelfLifeDays, input.EnableSerialNumber, input.MinStockQuantity, input.MaxStockQuantity, input.SafetyStockQuantity, input.ReorderPointQuantity);

            inventorySetting = await _repository.UpdateAsync(inventorySetting);

            var result = ObjectMapper.Map<ProductInventorySetting, ProductInventorySettingDto>(inventorySetting);

            await LoadOtherInfoAsync(new List<ProductInventorySettingDto> { result });

            return result;
        }

        #region
        private async Task LoadOtherInfoAsync(List<ProductInventorySettingDto> inventorySettings)
        {
            if (inventorySettings == null)
                return;

            foreach (var inventorySetting in inventorySettings)
            {
                var product = await _productRepository.GetAsync(inventorySetting.ProductId);

                inventorySetting.ProductCode = product?.Code;
                inventorySetting.ProductName = product?.Name;

                var warehouse = await _warehouseRepository.GetAsync(inventorySetting.DefaultWarehouseId);

                inventorySetting.DefaultWarehouseName = warehouse?.Name;

                var location = warehouse?.Locations?.FirstOrDefault(x => x.Id == inventorySetting.DefaultLocationId);

                inventorySetting.DefaultLocationName = location?.Name;

            }
        }
        #endregion
    }
}
